package edu.xlh.travel.service.impl;

import edu.xlh.travel.common.Result;
import edu.xlh.travel.dao.UserDao;
import edu.xlh.travel.pojo.User;
import edu.xlh.travel.service.AdminService;
import edu.xlh.travel.jwt.utils.JwtUtils;
import edu.xlh.travel.shiro.domin.DiyToken;
import edu.xlh.travel.util.RedisPipelined;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.servlet.ShiroHttpSession;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

@Service
@Transactional
public class AdminServiceImpl implements AdminService {
    @Autowired
    private UserDao userDao;
    @Autowired
    private BCryptPasswordEncoder encoder;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private RedisPipelined redisPipelined;


    public static final HashSet<HttpSession> sessionContext = new HashSet<HttpSession>();

    @Override
    public  Result login(Map<String, String> map , String verKey , HttpSession session , HttpServletResponse response) {
        //shiro执行登录认证的时候需要获取doGetAuthenticationInfo中设置的信息与token比较
        Subject subject= SecurityUtils.getSubject();
        DiyToken token=new DiyToken();
        //获取登录方式
        String login = map.get("name");
        //手机号正则，判断输入是否为手机号
        String ph = "^[1][3578]\\d{9}$";
        //邮箱正则，判断输入是否为邮箱
        String email = "^[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(\\.[a-zA-Z0-9_-]+)+$";
        //获取从前端传过来的验证码和redis中的验证码
        String vercode = map.get("vercode");
        //redisTemplate.setValueSerializer(RedisSerializer.string());
        //verKey = redisTemplate.getHashKeySerializer().serialize(verKey).toString();
        //String s = redisTemplate.getHashValueSerializer().deserialize(verKey.getBytes()).toString();
      //  String o =(String) redisTemplate.opsForValue().get(verKey);
        String value = redisPipelined.getCaptcha(verKey);
        if(StringUtils.isEmpty(vercode) || StringUtils.isEmpty(value)) {
            return new Result(203,"请输入验证码或者验证码已过期刷新页面");
        }
        if (login.matches(ph)) {
            String password = map.get("password");
            User user =findByMobileAndPassword(login , password);
            if(user != null) {
                //TODO
                if(!vercode.equals(value)) {
                    return new Result(204,"验证码错误，请重新输入");
                }
                //管理员标志判断
                String isAdmin = user.getPerm();
                if ("0".equals(isAdmin)) {
                    return new Result(205,"权限不足");
                }
                session.setAttribute("admin",user);
                Map<String , String> hashMap = new HashMap<>();
                hashMap.put("adminname",user.getName());
                token.setPhone(user.getMobile());
                token.setPassword(user.getPassword().toCharArray());
                subject.login(token);
                String jwtToken = JwtUtils.sign(user.getId(), JwtUtils.SECRET);
                redisTemplate.opsForValue().set(user.getId() , jwtToken.toString());
                hashMap.put("jwtToken", jwtToken);
                ((HttpServletResponse) response).setHeader(JwtUtils.AUTH_HEADER, jwtToken);
                return new Result(200,"登陆成功",hashMap);
            }else {
                return new Result(201,"登陆失败,请检查账号密码");
            }
        } else if (login.matches(email)) {
            String password = map.get("password");
            User user = findByEmailAndPassword(login , password);
            if(user != null) {
                /*if(!vercode.equals(value)) {
                    return new Result(204,"验证码错误，请重新输入");
                }*/
                //管理员标志判断
                String isAdmin = user.getPerm();
                if (!"1".equals(isAdmin)) {
                    return new Result(205,"权限不足");
                }
                session.setAttribute("admin",user);
                Map<String , String> hashMap = new HashMap<>();
                hashMap.put("adminname",user.getName());
                token.setEmail(user.getEmail());
                token.setPassword(user.getPassword().toCharArray());
                subject.login(token);
                String jwtToken = JwtUtils.sign(user.getId(), JwtUtils.SECRET);
                hashMap.put("jwtToken", jwtToken);
                ((HttpServletResponse) response).setHeader(JwtUtils.AUTH_HEADER, jwtToken);
                return new Result(200,"登陆成功",hashMap);
            }else {
                return new Result(201,"登陆失败,请检查账号密码");
            }
        } else{
            String password = map.get("password");
            List<User> adminList = findByName(login);
            User user = null;
            if(adminList != null) {
                if(!vercode.equals(value)) {
                    return new Result(204,"验证码错误，请重新输入");
                }
                for (User user1 : adminList) {
                    String encodedPassword = user1.getPassword();
                    String salt = user1.getSalt();
                    if (encoder.matches(password+salt,encodedPassword)) {
                        user = user1;
                        break;
                    }
                }
                session.setAttribute("admin",user);
                Map<String , String> hashMap = new HashMap<>();
                map.put("adminname",user.getName());
                token.setPhone(user.getMobile());
                token.setPassword(user.getPassword().toCharArray());
                return new Result(200,"登陆成功",map);
            } else {
            return new Result(203,"只能输入手机或者邮箱");
            }
        }
    }

    private List<User> findByName(String login) {
        return userDao.findByName(login);
    }

    @Override
    public User findByUsername(String username) {
        return null;
    }


    private User findByEmailAndPassword(String login, String password) {
        User user = userDao.findByEmail(login);
        String salt = user.getSalt();
        if(user!=null && encoder.matches(password+salt,user.getPassword())){
            return user;
        }else{
            return null;
        }
    }

    private User findByMobileAndPassword(String login, String password) {
        User user = userDao.findByMobile(login);
        String salt = user.getSalt();
        if(user!=null && encoder.matches(password+salt,user.getPassword())){
            return user;
        }else{
            return null;
        }
    }

}
